package com.dyp.myapp.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;


@Configuration
@EnableWebSecurity
/*
EnableMethodSecurity可以使用 @PreAuthorize、@PostAuthorize、@PreFilter、@PostFilter、@GetMapping、@PostMapping 等注解来声明方法级别的安全控制规则。
这些注解可以确保在方法被执行之前或之后应用过滤器、授权检查或其他的访问控制逻辑。例如，你可以使用 @PreAuthorize("hasRole('ADMIN')") 在一个方法上声明只有具有 ADMIN 角色的用户才能访问该方法。
*/
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfiguration {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        //csrf漏洞防御
//        http.csrf(Customizer.withDefaults()); //默认实现实际什么都没做
        http.csrf(csrf -> csrf.disable());
        /**
         * 旧版：.antMatchers("/admin/**").hasRole("ADMIN")
         * 新版：.requestMatchers("/admin/**").hasRole("ADMIN")
         */
        http
                // 配置角色，进行权接口权限的分配 
                .authorizeHttpRequests(authz -> authz
                        .requestMatchers("/api/authenticate").permitAll()
                        .requestMatchers("/management/health").permitAll()
                        .requestMatchers("/v3/api-docs/**").permitAll()
                        .requestMatchers("/swagger-ui/**").permitAll()
                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                        .requestMatchers("/api/**").authenticated() //
                        )
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));

        return http.build();
    }
}
